/**
 * 环境变量工具类
 * 
 * 提供类型安全、简洁优雅的环境变量获取方式
 * 纯静态方法设计，无需注入，直接使用
 * 
 * @example
 * ```ts
 * // 直接使用静态方法
 * const port = EnvUtil.getNumber('PORT', 3000);
 * const dbUrl = EnvUtil.get('DATABASE_URL'); // 必填项
 * const debug = EnvUtil.getBoolean('DEBUG', false);
 * const origins = EnvUtil.getArray('CORS_ORIGINS');
 * 
 * // 环境判断
 * if (EnvUtil.isDev) {
 *   console.log('开发环境');
 * }
 * 
 * // 批量检查
 * EnvUtil.require('DATABASE_URL', 'JWT_SECRET');
 * ```
 */
export class EnvUtil {
  // 禁止实例化，仅提供静态方法
  private constructor() {
    throw new Error('EnvUtil 是静态工具类，无需实例化');
  }

  // ============================================
  // 核心方法
  // ============================================

  /**
   * 获取环境变量（字符串）
   * 
   * @param key 环境变量键名
   * @param defaultValue 默认值（可选）
   * @returns 环境变量值
   * @throws 如果未找到且无默认值
   * 
   * @example
   * ```ts
   * const apiUrl = EnvUtil.get('API_URL');  // 必填
   * const title = EnvUtil.get('APP_TITLE', 'My App');  // 可选，带默认值
   * ```
   */
  static get(key: string, defaultValue?: string): string {
    const value = process.env[key] ?? defaultValue;
    if (value === undefined) {
      return EnvUtil.throwMissing(key);
    }
    return value;
  }

  /**
   * 获取环境变量（数字）
   * 
   * @param key 环境变量键名
   * @param defaultValue 默认值（可选）
   * @returns 数字值
   * @throws 如果未找到且无默认值，或转换失败
   * 
   * @example
   * ```ts
   * const port = EnvUtil.getNumber('PORT', 3000);
   * const timeout = EnvUtil.getNumber('TIMEOUT');
   * ```
   */
  static getNumber(key: string, defaultValue?: number): number {
    const value = EnvUtil.getOptional(key);
    
    if (value === undefined) {
      if (defaultValue !== undefined) {
        return defaultValue;
      }
      EnvUtil.throwMissing(key);
    }

    const num = Number(value);
    if (isNaN(num)) {
      throw new Error(`环境变量 ${key}="${value}" 无法转换为数字`);
    }
    return num;
  }

  /**
   * 获取环境变量（布尔值）
   * 
   * 支持的真值：'true', '1', 'yes', 'on'
   * 支持的假值：'false', '0', 'no', 'off', ''
   * 
   * @param key 环境变量键名
   * @param defaultValue 默认值（可选）
   * @returns 布尔值
   * 
   * @example
   * ```ts
   * const debug = EnvUtil.getBoolean('DEBUG', false);
   * const enableCache = EnvUtil.getBoolean('ENABLE_CACHE');
   * ```
   */
  static getBoolean(key: string, defaultValue?: boolean): boolean {
    const value = EnvUtil.getOptional(key);
    
    if (value === undefined) {
      if (defaultValue !== undefined) {
        return defaultValue;
      }
      return EnvUtil.throwMissing(key);
    }

    const lower = value.toLowerCase().trim();
    
    // 真值
    if (['true', '1', 'yes', 'on'].includes(lower)) {
      return true;
    }
    
    // 假值
    if (['false', '0', 'no', 'off', ''].includes(lower)) {
      return false;
    }

    throw new Error(
      `环境变量 ${key}="${value}" 无法转换为布尔值 (支持: true/false, 1/0, yes/no, on/off)`
    );
  }

  /**
   * 获取可选的环境变量
   * 
   * @param key 环境变量键名
   * @returns 环境变量值或 undefined
   * 
   * @example
   * ```ts
   * const token = EnvUtil.getOptional('API_TOKEN');
   * if (token) {
   *   // 使用 token
   * }
   * ```
   */
  static getOptional(key: string): string | undefined {
    return process.env[key];
  }

  /**
   * 获取环境变量（数组）
   * 
   * 支持逗号、分号、空格分隔
   * 
   * @param key 环境变量键名
   * @param defaultValue 默认值（可选）
   * @param separator 分隔符（默认: ','）
   * @returns 字符串数组
   * 
   * @example
   * ```ts
   * // CORS_ORIGINS=http://localhost:3000,http://localhost:4200
   * const origins = EnvUtil.getArray('CORS_ORIGINS');
   * // ['http://localhost:3000', 'http://localhost:4200']
   * ```
   */
  static getArray(key: string, defaultValue?: string[], separator = ','): string[] {
    const value = EnvUtil.getOptional(key);
    
    if (value === undefined) {
      if (defaultValue !== undefined) {
        return defaultValue;
      }
      return EnvUtil.throwMissing(key);
    }

    return value
      .split(separator)
      .map((item) => item.trim())
      .filter((item) => item.length > 0);
  }

  // ============================================
  // 便捷方法
  // ============================================

  /**
   * 判断是否为生产环境
   */
  static get isProd(): boolean {
    return EnvUtil.getNodeEnv() === 'production';
  }

  /**
   * 判断是否为开发环境
   */
  static get isDev(): boolean {
    return EnvUtil.getNodeEnv() === 'development';
  }

  /**
   * 判断是否为测试环境
   */
  static get isTest(): boolean {
    return EnvUtil.getNodeEnv() === 'test';
  }

  /**
   * 获取 NODE_ENV
   */
  static getNodeEnv(): string {
    return EnvUtil.get('NODE_ENV', 'development');
  }

  /**
   * 获取端口号
   */
  static getPort(): number {
    return EnvUtil.getNumber('PORT', 3000);
  }

  /**
   * 检查环境变量是否存在
   * 
   * @param key 环境变量键名
   * @returns 是否存在
   */
  static has(key: string): boolean {
    return EnvUtil.getOptional(key) !== undefined;
  }

  /**
   * 批量检查必需的环境变量
   * 
   * @param keys 环境变量键名数组
   * @throws 如果有任何一个缺失
   * 
   * @example
   * ```ts
   * EnvUtil.require('DATABASE_URL', 'JWT_SECRET', 'REDIS_HOST');
   * ```
   */
  static require(...keys: string[]): void {
    const missing = keys.filter((key) => !EnvUtil.has(key));
    
    if (missing.length > 0) {
      throw new Error(
        `缺少必需的环境变量:\n  - ${missing.join('\n  - ')}\n` +
        `请检查 .env 文件或环境变量配置`
      );
    }
  }

  // ============================================
  // 私有辅助方法
  // ============================================

  private static throwMissing(key: string): never {
    throw new Error(
      `环境变量 ${key} 未设置且无默认值\n` +
      `请在 .env 文件中配置或提供默认值`
    );
  }
}
